package org.linlinjava.litemall.admin.service;

import com.github.binarywang.wxpay.bean.request.WxPayRefundRequest;
import com.github.binarywang.wxpay.bean.result.WxPayRefundResult;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.linlinjava.litemall.core.notify.NotifyService;
import org.linlinjava.litemall.core.notify.NotifyType;
import org.linlinjava.litemall.core.redis.RedisCache;
import org.linlinjava.litemall.core.template.WxMpMsgTemplateService;
import org.linlinjava.litemall.core.util.JacksonUtil;
import org.linlinjava.litemall.core.util.ResponseUtil;
import org.linlinjava.litemall.db.domain.*;
import org.linlinjava.litemall.db.service.*;
import org.linlinjava.litemall.db.util.CouponUserConstant;
import org.linlinjava.litemall.db.util.OrderUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static org.linlinjava.litemall.admin.util.AdminResponseCode.*;

@Service

public class AdminOrderService {
	private final Log logger = LogFactory.getLog(AdminOrderService.class);

	@Autowired
	private LitemallOrderGoodsService orderGoodsService;
	@Autowired
	private LitemallOrderService orderService;
	@Autowired
	private LitemallGoodsProductService productService;
	@Autowired
	private LitemallUserService userService;
	@Autowired
	private LitemallCommentService commentService;
	@Autowired
	private WxPayService wxPayService;
	@Autowired
	private NotifyService notifyService;
	@Autowired
	private LogHelper logHelper;
	@Autowired
	private LitemallCouponUserService couponUserService;
	@Autowired
	private LitemallShopService shopService;
	@Autowired
	private WxMpMsgTemplateService wxMpMsgTemplateService;
	@Autowired
	private LitemallShopBalanceLogService ShopBalanceLogService;
	@Autowired
	private LitemallShopBalanceService shopBalanceService;
	
	@Autowired
	private RedisCache redisCache;

	public Object list(Integer userId, String orderSn, String mobile, LocalDateTime start, LocalDateTime end,
			List<Short> orderStatusArray, Integer page, Integer limit, String sort, String order) {
		List<LitemallOrder> orderList = orderService.querySelective(userId, orderSn, mobile, start, end,
				orderStatusArray, page, limit, sort, order);
		// 用户id
		List<Integer> userIdList = orderList.stream().map(LitemallOrder::getUserId).collect(Collectors.toList());
		if (userIdList.size() < 1) {
			return ResponseUtil.okList(orderList);
		}
		// 商铺id
		List<Integer> shopIdList = orderList.stream().map(LitemallOrder::getShopId).collect(Collectors.toList());
		List<LitemallShop> shopList = shopService.queryByListShopId(shopIdList);
		List<LitemallUser> UserList = userService.queryByListUserId(userIdList);
		// orderList.get(0).setNickname(nickname);
		// UserList.get(0).getNickname()
		// UserList.stream().forEach(userList ->orderList.get(index) );
		for (int i = 0; i < orderList.size(); i++) {
			for (int j = 0; j < UserList.size(); j++) {
				if (UserList.get(j).getId().equals(orderList.get(i).getUserId())) {
					orderList.get(i).setNickname(UserList.get(j).getNickname());
					orderList.get(i).setAvatar(UserList.get(j).getAvatar());
				}
			}
			for (int k = 0; k < shopList.size(); k++) {
				if (shopList.get(k).getId().equals(orderList.get(i).getShopId())) {
					orderList.get(i).setShopName(shopList.get(k).getShopName());
					if(StringUtils.isEmpty(orderList.get(i).getShipChannel())) {
						orderList.get(i).setShipChannel(redisCache.getCacheObject("shop_print_" + orderList.get(i).getShopId() + "_" + orderList.get(i).getShipSn()));
					}
				}
				if (orderList.get(i).getShopId() == 0) {// 门店为0说明是送货上门
					orderList.get(i).setShopName("送货上门");
				}
			}
		}
		return ResponseUtil.okList(orderList);
	}

	public Object Merchantlist(LitemallAdmin admin, Integer userId, String orderSn, String mobile, LocalDateTime start, LocalDateTime end,
			List<Short> orderStatusArray, Integer page, Integer limit, String sort, String order) {
		
		List<LitemallOrder> orderList = orderService.Merchant_querySelective(admin, userId, orderSn, mobile, start, end,
				orderStatusArray, page, limit, sort, order);
		//用户id
		List<Integer> userIdList = orderList.stream().map(LitemallOrder::getUserId).collect(Collectors.toList());
		if (userIdList.size() < 1) {
			return ResponseUtil.okList(orderList);
		}
		//商铺id
		List<Integer> shopIdList = orderList.stream().map(LitemallOrder::getShopId).collect(Collectors.toList());
		List<LitemallShop> shopList = shopService.queryByListShopId(shopIdList);
		List<LitemallUser> UserList = userService.queryByListUserId(userIdList);
		//orderList.get(0).setNickname(nickname);
		//UserList.get(0).getNickname()
		//UserList.stream().forEach(userList ->orderList.get(index) );
		for (int i = 0; i < orderList.size(); i++) {
			for (int j = 0; j < UserList.size(); j++) {
				if (UserList.get(j).getId().equals(orderList.get(i).getUserId())) {
					orderList.get(i).setNickname(UserList.get(j).getNickname());
					orderList.get(i).setAvatar(UserList.get(j).getAvatar());
				}
			}
			for (int k = 0; k < shopList.size(); k++) {
				if (shopList.get(k).getId().equals(orderList.get(i).getShopId())) {
					orderList.get(i).setShopName(shopList.get(k).getShopName());
				}
				if (orderList.get(i).getShopId() == 0) {// 门店为0说明是送货上门
					orderList.get(i).setShopName("送货上门");
				}
			}
		}
		return ResponseUtil.okList(orderList);
	}

	public Object detail(Integer id) {
		LitemallOrder order = orderService.findById(id);
		List<LitemallOrderGoods> orderGoods = orderGoodsService.queryByOid(id);
		UserVo user = userService.findUserVoById(order.getUserId());
		Map<String, Object> data = new HashMap<>();
		data.put("order", order);
		data.put("orderGoods", orderGoods);
		data.put("user", user);

		return ResponseUtil.ok(data);
	}

	/**
	 * 订单退款
	 * <p>
	 * 1. 检测当前订单是否能够退款; 2. 微信退款操作; 3. 设置订单退款确认状态； 4. 订单商品库存回库。
	 * <p>
	 * TODO 虽然接入了微信退款API，但是从安全角度考虑，建议开发者删除这里微信退款代码，采用以下两步走步骤： 1.
	 * 管理员登录微信官方支付平台点击退款操作进行退款 2. 管理员登录litemall管理后台点击退款操作进行订单状态修改和商品库存回库
	 *
	 * @param body 订单信息，{ orderId：xxx }
	 * @return 订单退款操作结果
	 */
	@Transactional
	public Object refund(String body) {
		Integer orderId = JacksonUtil.parseInteger(body, "orderId");
		String refundMoney = JacksonUtil.parseString(body, "refundMoney");
		if (orderId == null) {
			return ResponseUtil.badArgument();
		}
		/*
		if (StringUtils.isEmpty(refundMoney)) {
			return ResponseUtil.badArgument();
		}*/

		LitemallOrder order = orderService.findById(orderId);
		if (order == null) {
			return ResponseUtil.badArgument();
		}
		/*
		if (order.getActualPrice().compareTo(new BigDecimal(refundMoney)) != 0) {
			return ResponseUtil.badArgumentValue();
		}
		
		// 如果订单不是退款状态，则不能退款
		if (!order.getOrderStatus().equals(OrderUtil.STATUS_REFUND)) {
			return ResponseUtil.fail(ORDER_CONFIRM_NOT_ALLOWED, "订单不能确认收货");
		}*/

		// 微信退款
		WxPayRefundRequest wxPayRefundRequest = new WxPayRefundRequest();
		wxPayRefundRequest.setOutTradeNo(order.getOrderSn());
		wxPayRefundRequest.setOutRefundNo("refund_" + order.getOrderSn());
		// 元转成分
		Integer totalFee = order.getActualPrice().multiply(new BigDecimal(100)).intValue();
		wxPayRefundRequest.setTotalFee(totalFee);
		wxPayRefundRequest.setRefundFee(totalFee);

		WxPayRefundResult wxPayRefundResult;
		try {
			wxPayRefundResult = wxPayService.refund(wxPayRefundRequest);
		} catch (WxPayException e) {
			logger.error(e.getMessage(), e);
			return ResponseUtil.fail(ORDER_REFUND_FAILED, "订单退款失败");
		}
		if (!wxPayRefundResult.getReturnCode().equals("SUCCESS")) {
			logger.warn("refund fail: " + wxPayRefundResult.getReturnMsg());
			return ResponseUtil.fail(ORDER_REFUND_FAILED, "订单退款失败");
		}
		if (!wxPayRefundResult.getResultCode().equals("SUCCESS")) {
			logger.warn("refund fail: " + wxPayRefundResult.getReturnMsg());
			return ResponseUtil.fail(ORDER_REFUND_FAILED, "订单退款失败");
		}

		LocalDateTime now = LocalDateTime.now();
		// 设置订单取消状态
		order.setOrderStatus(OrderUtil.STATUS_REFUND_CONFIRM);
		order.setEndTime(now);
		// 记录订单退款相关信息
		order.setRefundAmount(order.getActualPrice());
		order.setRefundType("微信退款接口");
		order.setRefundContent(wxPayRefundResult.getRefundId());
		order.setRefundTime(now);
		if (orderService.updateWithOptimisticLocker(order) == 0) {
			throw new RuntimeException("更新数据已失效");
		}

		// 商品货品数量增加
		List<LitemallOrderGoods> orderGoodsList = orderGoodsService.queryByOid(orderId);
		for (LitemallOrderGoods orderGoods : orderGoodsList) {
			Integer productId = orderGoods.getProductId();
			Short number = orderGoods.getNumber();
			if (productService.addStock(productId, number) == 0) {
				throw new RuntimeException("商品货品库存增加失败");
			}
		}

		// 返还优惠券
		List<LitemallCouponUser> couponUsers = couponUserService.findByOid(orderId);
		for (LitemallCouponUser couponUser : couponUsers) {
			// 优惠券状态设置为可使用
			couponUser.setStatus(CouponUserConstant.STATUS_USABLE);
			couponUser.setUpdateTime(LocalDateTime.now());
			couponUserService.update(couponUser);
		}

		// TODO 发送邮件和短信通知，这里采用异步发送
		// 退款成功通知用户, 例如“您申请的订单退款 [ 单号:{1} ] 已成功，请耐心等待到账。”
		// 注意订单号只发后6位
		notifyService.notifySmsTemplate(order.getMobile(), NotifyType.REFUND,
				new String[] { order.getOrderSn().substring(8, 14) });

		logHelper.logOrderSucceed("退款", "订单编号 " + order.getOrderSn());
		return ResponseUtil.ok();
	}

	
	@Transactional
	public Object refund(Integer orderId) {
		//Integer orderId = JacksonUtil.parseInteger(body, "orderId");
		//String refundMoney = JacksonUtil.parseString(body, "refundMoney");
		if (orderId == null) {
			return ResponseUtil.badArgument();
		}
		/*
		if (StringUtils.isEmpty(refundMoney)) {
			return ResponseUtil.badArgument();
		}*/

		LitemallOrder order = orderService.findById(orderId);
		if (order == null) {
			return ResponseUtil.badArgument();
		}
		/*
		if (order.getActualPrice().compareTo(new BigDecimal(refundMoney)) != 0) {
			return ResponseUtil.badArgumentValue();
		}
		int result = 0;
		if(order.getOrderStatus().equals(OrderUtil.STATUS_PAY)) {
			result = 1;
		}
		// 如果订单不是退款状态，则不能退款
		if (!order.getOrderStatus().equals(OrderUtil.STATUS_REFUND)) {
			if(result==0) {
				return ResponseUtil.fail(ORDER_CONFIRM_NOT_ALLOWED, "订单不能确认收货");	
			}
		}*/

		// 微信退款
		WxPayRefundRequest wxPayRefundRequest = new WxPayRefundRequest();
		wxPayRefundRequest.setOutTradeNo(order.getOrderSn());
		wxPayRefundRequest.setOutRefundNo("refund_" + order.getOrderSn());
		// 元转成分
		Integer totalFee = order.getActualPrice().multiply(new BigDecimal(100)).intValue();
		wxPayRefundRequest.setTotalFee(totalFee);
		wxPayRefundRequest.setRefundFee(totalFee);

		WxPayRefundResult wxPayRefundResult;
		try {
			wxPayRefundResult = wxPayService.refund(wxPayRefundRequest);
		} catch (WxPayException e) {
			logger.error(e.getMessage(), e);
			return ResponseUtil.fail(ORDER_REFUND_FAILED, "订单退款失败");
		}
		if (!wxPayRefundResult.getReturnCode().equals("SUCCESS")) {
			logger.warn("refund fail: " + wxPayRefundResult.getReturnMsg());
			return ResponseUtil.fail(ORDER_REFUND_FAILED, "订单退款失败");
		}
		if (!wxPayRefundResult.getResultCode().equals("SUCCESS")) {
			logger.warn("refund fail: " + wxPayRefundResult.getReturnMsg());
			return ResponseUtil.fail(ORDER_REFUND_FAILED, "订单退款失败");
		}

		LocalDateTime now = LocalDateTime.now();
		// 设置订单取消状态
		order.setOrderStatus(OrderUtil.STATUS_REFUND_CONFIRM);
		order.setEndTime(now);
		// 记录订单退款相关信息
		order.setRefundAmount(order.getActualPrice());
		order.setRefundType("微信退款接口");
		order.setRefundContent(wxPayRefundResult.getRefundId());
		order.setRefundTime(now);
		if (orderService.updateWithOptimisticLocker(order) == 0) {
			throw new RuntimeException("更新数据已失效");
		}

		//修改商家收入记录
		//orderId
		LitemallShopBalanceLog shopBalanceLog = ShopBalanceLogService.getOneShopBalanceLogByorderId(orderId);
		//如果订单已结算，直接从商家余额扣
		if(shopBalanceLog.getStatus() == 1) {
			//从商家余额扣除
			int res = shopBalanceService.updataShopBalance(shopBalanceLog);
			if(res == 0) {
				System.out.println("商家退款扣减余额出错！！！！");
			}
		}else {
			shopBalanceLog.setStatus(2);
			ShopBalanceLogService.updateShopBalanceLog(shopBalanceLog);
		}

		
		// 商品货品数量增加
		List<LitemallOrderGoods> orderGoodsList = orderGoodsService.queryByOid(orderId);
		for (LitemallOrderGoods orderGoods : orderGoodsList) {
			Integer productId = orderGoods.getProductId();
			Short number = orderGoods.getNumber();
			if (productService.addStock(productId, number) == 0) {
				throw new RuntimeException("商品货品库存增加失败");
			}
		}

		// 返还优惠券
		List<LitemallCouponUser> couponUsers = couponUserService.findByOid(orderId);
		for (LitemallCouponUser couponUser : couponUsers) {
			// 优惠券状态设置为可使用
			couponUser.setStatus(CouponUserConstant.STATUS_USABLE);
			couponUser.setUpdateTime(LocalDateTime.now());
			couponUserService.update(couponUser);
		}

		// TODO 发送邮件和短信通知，这里采用异步发送
		// 退款成功通知用户, 例如“您申请的订单退款 [ 单号:{1} ] 已成功，请耐心等待到账。”
		// 注意订单号只发后6位
		notifyService.notifySmsTemplate(order.getMobile(), NotifyType.REFUND,
				new String[] { order.getOrderSn().substring(8, 14) });

		logHelper.logOrderSucceed("退款", "订单编号 " + order.getOrderSn());
		return ResponseUtil.ok();
	}
	
	/**
	 * 发货 1. 检测当前订单是否能够发货 2. 设置订单发货状态
	 *
	 * @param body 订单信息，{ orderId：xxx, shipSn: xxx, shipChannel: xxx }
	 * @return 订单操作结果 成功则 { errno: 0, errmsg: '成功' } 失败则 { errno: XXX, errmsg: XXX }
	 */
	public Object ship(String body) {
		Integer orderId = JacksonUtil.parseInteger(body, "orderId");
		String shipSn = JacksonUtil.parseString(body, "shipSn");
		String shipChannel = JacksonUtil.parseString(body, "shipChannel");
		if (orderId == null || shipSn == null || shipChannel == null) {
			return ResponseUtil.badArgument();
		}

		LitemallOrder order = orderService.findById(orderId);
		if (order == null) {
			return ResponseUtil.badArgument();
		}

		// 如果订单不是已付款状态，则不能发货
		if (!order.getOrderStatus().equals(OrderUtil.STATUS_PAY)) {
			return ResponseUtil.fail(ORDER_CONFIRM_NOT_ALLOWED, "订单不能确认收货");
		}

		order.setOrderStatus(OrderUtil.STATUS_SHIP);
		order.setShipSn(shipSn);
		// order.setShipChannel(shipChannel);
		order.setShipChannel("91闪送");
		order.setShipTime(LocalDateTime.now());
		if (orderService.updateWithOptimisticLocker(order) == 0) {
			return ResponseUtil.updatedDateExpired();
		}

		// TODO 发送邮件和短信通知，这里采用异步发送
		// 发货会发送通知短信给用户: *
		// "您的订单已经发货，快递公司 {1}，快递单 {2} ，请注意查收"
		notifyService.notifySmsTemplate(order.getMobile(), NotifyType.SHIP, new String[] { shipChannel, shipSn });

		// wxMpMsgTemplateService.manualSend(order.getOrderSn(),null);

		logHelper.logOrderSucceed("发货", "订单编号 " + order.getOrderSn());
		return ResponseUtil.ok();
	}

	/**
	 * 删除订单 1. 检测当前订单是否能够删除 2. 删除订单
	 *
	 * @param body 订单信息，{ orderId：xxx }
	 * @return 订单操作结果 成功则 { errno: 0, errmsg: '成功' } 失败则 { errno: XXX, errmsg: XXX }
	 */
	public Object delete(String body) {
		Integer orderId = JacksonUtil.parseInteger(body, "orderId");
		LitemallOrder order = orderService.findById(orderId);
		if (order == null) {
			return ResponseUtil.badArgument();
		}

		// 如果订单不是关闭状态(已取消、系统取消、已退款、用户已确认、系统已确认)，则不能删除
		Short status = order.getOrderStatus();
		if (!status.equals(OrderUtil.STATUS_CANCEL) && !status.equals(OrderUtil.STATUS_AUTO_CANCEL)
				&& !status.equals(OrderUtil.STATUS_CONFIRM) && !status.equals(OrderUtil.STATUS_AUTO_CONFIRM)
				&& !status.equals(OrderUtil.STATUS_REFUND_CONFIRM)) {
			return ResponseUtil.fail(ORDER_DELETE_FAILED, "订单不能删除");
		}
		// 删除订单
		orderService.deleteById(orderId);
		// 删除订单商品
		orderGoodsService.deleteByOrderId(orderId);
		logHelper.logOrderSucceed("删除", "订单编号 " + order.getOrderSn());
		return ResponseUtil.ok();
	}

	/**
	 * 回复订单商品
	 *
	 * @param body 订单信息，{ orderId：xxx }
	 * @return 订单操作结果 成功则 { errno: 0, errmsg: '成功' } 失败则 { errno: XXX, errmsg: XXX }
	 */
	public Object reply(String body) {
		Integer commentId = JacksonUtil.parseInteger(body, "commentId");
		if (commentId == null || commentId == 0) {
			return ResponseUtil.badArgument();
		}
		// 目前只支持回复一次
		LitemallComment comment = commentService.findById(commentId);
		if (comment == null) {
			return ResponseUtil.badArgument();
		}
		if (!StringUtils.isEmpty(comment.getAdminContent())) {
			return ResponseUtil.fail(ORDER_REPLY_EXIST, "订单商品已回复！");
		}
		String content = JacksonUtil.parseString(body, "content");
		if (StringUtils.isEmpty(content)) {
			return ResponseUtil.badArgument();
		}
		// 更新评价回复
		comment.setAdminContent(content);
		commentService.updateById(comment);

		return ResponseUtil.ok();
	}
	

	public Object buildOrder(String body) {
		Integer orderId = JacksonUtil.parseInteger(body, "orderId");
		LitemallOrder order = orderService.findById(orderId);
		if (order == null) {
			return ResponseUtil.badArgument();
		}
		Short status = order.getOrderStatus();
		if(!status.equals(OrderUtil.STATUS_PAY)) {
			return ResponseUtil.fail(ORDER_DELETE_FAILED, "订单未付款，不能接单");
		}
		LitemallOrder o = new LitemallOrder();
		o.setId(order.getId());
		o.setOrderStatus(OrderUtil.STATUS_MAKE);
		o.setUpdateTime(LocalDateTime.now());
		orderService.buildOrder(o);
		
		return ResponseUtil.ok();
	}
}
